package com.easybbs.controller;

import com.easybbs.annotation.Globallnterceptor;
import com.easybbs.annotation.VerifyParam;
import com.easybbs.entity.constants.Constants;
import com.easybbs.entity.dto.CreateImageCode;
import com.easybbs.entity.dto.SessionWebUserDto;
import com.easybbs.entity.dto.SysSetting4CommentDto;
import com.easybbs.entity.dto.SysSettingDto;
import com.easybbs.entity.enums.ResponseCodeEnum;
import com.easybbs.entity.enums.VerifyRegexEnum;
import com.easybbs.entity.vo.ResponseVO;
import com.easybbs.exception.BusinessException;
import com.easybbs.service.EmailCodeService;
import com.easybbs.service.UserInfoService;
import com.easybbs.utils.StringTools;
import com.easybbs.utils.SysCacheUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@RestController
public class AccountController extends BaseController {
    @Autowired
    private EmailCodeService emailCodeService;
    @Autowired
    private UserInfoService userInfoService;

    /**
     * 获取验证码
     *
     * @param userId
     * @return
     */
    @RequestMapping("/checkCode")
    public void checkCode(HttpServletResponse response, HttpSession session, Integer type) throws IOException {
        CreateImageCode vCode = new CreateImageCode(160, 44, 4, 10);
        //浏览器不缓存数据
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        //每次都从服务器获取数据保证每次数据都是最新的
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        String code = vCode.getCode();
        //登录注册
        if (type == null || type == 0) {
            //将验证码存入session进行对比
            session.setAttribute(Constants.CHECK_CODE_KEY, code);
        } else {
            //获取重置密码
            session.setAttribute(Constants.CHECK_CODE_KEY_EMAIL, code);
        }
        vCode.write(response.getOutputStream());
    }

    /**
     * 发送邮箱验证码
     *
     * @param session
     * @param email
     * @param checkCode
     * @param type
     * @return
     */
    @RequestMapping("/sendEmailCode")
    @Globallnterceptor(checkParams = true)
    public ResponseVO sendEmailCode(HttpSession session,
                                    @VerifyParam(required = true) String email,
                                    @VerifyParam(required = true) String checkCode,
                                    @VerifyParam(required = true) Integer type) {
        try {
//            已经使用aop面向切面解决参数校验
//            if (StringTools.isEmpty(email) || StringTools.isEmpty(checkCode) || type == null) {
//                throw new BusinessException(ResponseCodeEnum.CODE_600);
//            }
            //判断验证码是否和输入的一致
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
                throw new BusinessException("图片验证码错误");
            }
            emailCodeService.sendEmailCode(email, type);
            return getSuccessResponseVO(null);
        } finally {
            //验证码只能发送一次 清除session中存储的验证码数据
            session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL);
        }
    }

    /**
     * 注册
     *
     * @param session
     * @param checkCode
     * @return
     */
    @RequestMapping("/register")
    @Globallnterceptor(checkParams = true)
    public ResponseVO register(HttpSession session,
                               @VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
                               @VerifyParam(required = true) String emailCode,
                               @VerifyParam(required = true, max = 20) String nickName,
                               @VerifyParam(required = true, max = 18, min = 8, regex = VerifyRegexEnum.PASSWORD) String password,
                               @VerifyParam(required = true) String checkCode) {
        try {
            //判断传递的这些参数是否为空
//            if (StringTools.isEmpty(email) || StringTools.isEmpty(emailCode) || StringTools.isEmpty(nickName) || StringTools.isEmpty(password) || StringTools.isEmpty(checkCode)) {
//                throw new BusinessException(ResponseCodeEnum.CODE_600);
//            }

            //判断验证码是否和输入的一致
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码错误");
            }
            userInfoService.register(email, emailCode, nickName, password);
            return getSuccessResponseVO(null);
        } finally {
            //验证码只能发送一次 清除session中存储的验证码数据
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 登录
     *
     * @param session
     * @param email
     * @param password
     * @param checkCode
     * @return
     */
    @RequestMapping("/login")
    @Globallnterceptor(checkParams = true)
    public ResponseVO login(HttpSession session,
                            HttpServletRequest request,
                            @VerifyParam(required = true) String email,
                            @VerifyParam(required = true) String password,
                            @VerifyParam(required = true) String checkCode) {
        try {
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码错误");
            }
            //登录的用户信息
            SessionWebUserDto sessionWebUserDto = userInfoService.login(email, password, getIpAddr(request));
            //将用户登录信息和用户id存入到session中
            session.setAttribute(Constants.SESSION_KEY, sessionWebUserDto);
            return getSuccessResponseVO(sessionWebUserDto);
        } finally {
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }

    /**
     * 获取登录用户信息
     *
     * @param session
     * @return
     */
    @RequestMapping("/getUserInfo")
    @Globallnterceptor()
    public ResponseVO getUserInfo(HttpSession session) {
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
        return getSuccessResponseVO(sessionWebUserDto);
    }

    /**
     * 退出登录
     *
     * @param session
     * @return
     */
    @RequestMapping("/logout")
    @Globallnterceptor()
    public ResponseVO logout(HttpSession session) {
        session.invalidate();
        return getSuccessResponseVO(null);
    }

    /**
     * 获取评论开关
     * 详解：
     * 系统配置是否打开评论 （每个地方都要用到）
     *
     * @param session
     * @return
     */
    @RequestMapping("/getSysSetting")
    @Globallnterceptor()
    public ResponseVO getSysSetting() {
        SysSettingDto sysSettingDto = SysCacheUtils.getSysSetting();
        //获取评论配置类的评论是否开启配置的类
        SysSetting4CommentDto commentSetting = sysSettingDto.getCommentSetting();
        Map<String, Object> result = new HashMap<>();
        result.put("commentOpen", commentSetting.getCommentOpen());
        return getSuccessResponseVO(result);
    }

    /**
     * 重置密码
     *
     * @return
     */
    @RequestMapping("/resetPwd")
    @Globallnterceptor(checkParams = true)
    public ResponseVO resetPwd(HttpSession session,
                               @VerifyParam(required = true) String email,
                               @VerifyParam(required = true, max = 18, min = 8, regex = VerifyRegexEnum.PASSWORD) String password,
                               @VerifyParam(required = true) String emailCode,
                               @VerifyParam(required = true) String checkCode
    ) {
        try {
            //判断验证码是否和输入的一致
            if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
                throw new BusinessException("图片验证码错误");
            }
            //重置密码逻辑方法
            userInfoService.resetPwd(email, password, emailCode);

            return getSuccessResponseVO(null);
        } finally {
            //不论请求成功或者失败都需要清除checkCode
            session.removeAttribute(Constants.CHECK_CODE_KEY);
        }
    }
}
